package temporaryCache

import (
	"errors"
	"git.huoys.com/block_chain/mall/pkg/redisCache"
	"git.huoys.com/block_chain/mall/pkg/redisCache/common"
	"github.com/go-redis/redis"
	"time"
)

type temporaryCache struct {
	redis redis.Cmdable
}

func NewTemporaryCache(redisConn redis.Cmdable) redisCache.RedisCache {
	return &temporaryCache{
		redis: redisConn,
	}
}

// 缓存，或者锁是否存在
func (c temporaryCache) Exist(key string) (bool, error) {
	result, err := c.redis.Exists(key).Result()
	if err != nil {
		if errors.Is(err, redis.Nil) {
			return false, nil
		}
		return false, err
	}
	if result > 0 {
		return true, nil
	} else {
		return false, nil
	}
}

// 添加缓存
func (c temporaryCache) CacheAdd(key string, value interface{}, cacheTtl, lockTtl time.Duration, requestId int) (err error) {
	// 等待锁释放
	err = c.WaitLock(key)
	if err != nil {
		return err
	}
	// 添加锁
	_, err = c.TryLock(key, requestId, lockTtl)
	defer c.UnLock(key, requestId)
	if err != nil {
		return err
	}
	// 添加缓存/统一缓存为json
	val, err := common.Marshal(value)
	if err != nil {
		return err
	}
	err = c.redis.Set(key, val, cacheTtl).Err()
	if err != nil {
		return err
	}
	return err
}

// 添加多条缓存
func (c temporaryCache) CacheAddMultiple(cache map[string]interface{}, cacheTtl, lockTtl time.Duration, requestId int) (err error) {
	for key, value := range cache {
		err = c.CacheAdd(key, value, cacheTtl, lockTtl, requestId)
		if err != nil {
			return err
		}
	}
	return nil
}

// 删除缓存
func (c temporaryCache) CacheDel(key string) error {
	return c.redis.Del(key).Err()
}

// 获取单条缓存
func (c temporaryCache) CacheGet(key string) (value []byte, err error) {
	value, err = c.redis.Get(key).Bytes()
	if err != nil {
		return nil, err
	}
	// 可能会添加0值，在此处过滤
	if len(value) <= 1 {
		return nil, nil
	}
	return
}

// 获取多条缓存
func (c temporaryCache) CacheGetMultiple(keys []string) (value [][]byte, err error) {
	var tx = c.redis.TxPipeline()
	for _, item := range keys {
		tx.Get(item)
	}
	result, err := tx.Exec()
	if err != nil && !errors.Is(err, redis.Nil) {
		return nil, err
	} else if errors.Is(err, redis.Nil) { // 过滤没有查询到的错误
		err = nil
	}
	for _, item := range result {
		res := item.(*redis.StringCmd)
		info, err := res.Bytes()
		if err != nil && !errors.Is(err, redis.Nil) {
			return nil, err
		}
		if errors.Is(err, redis.Nil) || len(info) == 0 {
			continue
		}
		value = append(value, info)
	}
	return
}
